﻿using DevExpress.Mvvm.DataAnnotations;
using Microsoft.WindowsAPICodePack.Shell;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Imaging;
using VideoLib.Config;
using VideoLib.Models;
using VideoLib.Utils;
using Application = System.Windows.Application;

namespace VideoLib.ViewModels
{
    [POCOViewModel]
    public class MainViewModel
    {
        public MainViewModel()
        {
            InitVideo();
            App.MainViewModel = this;
        }

        public virtual ObservableCollection<FolderInfo> Folders { get; set; } = new ObservableCollection<FolderInfo>();

        public virtual ObservableCollection<PreviewInfo> PreviewImage { get; set; } = new ObservableCollection<PreviewInfo>();
        public virtual int ThumbNum { get; set; } = 12;

        public virtual bool IsLoadingThumb { get; set; }

        public virtual int AllVideoCount { get; set; }

        public virtual int ZoomFactor { get; set; } = 1;

        public const string BasePath = "F:\\";

        static string[] extsVideo = new[] { ".mp4", ".avi", ".mkv", ".mov", ".flv" };
        static string[] extsImg = new[] { ".jpg", ".png" };
        public async void InitVideo()
        {
            Folders?.Clear();
            if (!File.Exists("setting.json"))
            {
                return;
            }

            var list = AppConfig.Instance.VideoPath;
            foreach (var item in list)
            {
                if (Directory.Exists(item))
                {
                    await GetVideoFiles(item);
                }
            }
        }

        public void OpenVideo(VideoInfo video)
        {
            if (!File.Exists(AppConfig.Instance.PlayerPath))
            {
                return;
            }

            Process process = new Process();
            process.StartInfo.FileName = AppConfig.Instance.PlayerPath;
            process.StartInfo.Arguments = video.Path;
            process.Start();
        }

        // 递归获取文件夹下所有视频文件
        private async Task GetVideoFiles(string path)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);
            FolderInfo folder = new FolderInfo()
            {
                Direction = directoryInfo.FullName,
            };

            Folders.Add(folder);

            try
            {
                foreach (var file in directoryInfo.GetFiles())
                {
                    if (extsVideo.Contains(file.Extension.ToLower()) || (extsImg.Contains(file.Extension.ToLower()) && AppConfig.Instance.ShowImage))
                    {
                        VideoInfo video = new VideoInfo()
                        {
                            Name = Path.GetFileNameWithoutExtension(file.FullName),
                            Path = file.FullName,
                            Thumb = await ThumbHelper.GetThumbnailByPath(file.FullName),
                        };

                        folder.Videos.Add(video);
                        await Task.Delay(30);
                    }
                }

                // 计算视频总数
                AllVideoCount = Folders.Sum(f => f.Videos.Count);
                if (folder.Videos.Count == 0)
                {
                    Folders.Remove(folder);
                }

                foreach (var directory in directoryInfo.GetDirectories())
                {
                    _ = GetVideoFiles(directory.FullName);
                    await Task.Delay(100);
                }
            }
            catch (Exception)
            {
                return;
            }
        }

        public void OpenFolder(VideoInfo video)
        {
            var directory = Path.GetDirectoryName(video.Path);
            if (Directory.Exists(directory))
            {
                // 打开文件夹
                Process.Start("explorer", "/select,\"" + video.Path + "\"");
            }
        }

        public void ShowThumbWindow()
        {
            if (PreviewImage.Count == 0)
            {
                return;
            }
            ThumbWindow thumbWindow = new(PreviewImage, previewVideo.Name ?? string.Empty)
            {
                Owner = Application.Current.MainWindow,
                WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner
            };
            thumbWindow.Show();
        }

        VideoInfo previewVideo;
        public async void PreviewVideo(VideoInfo video)
        {
            if (!File.Exists(FFmpegHelper.ffmpegPath))
            {
                MessageBox.Show("ffmpeg未找到，请检查程序目录下ffmpeg\\ffmpeg.exe是否存在！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (video == null || video.Path == null)
            {
                return;
            }

            if (!Directory.Exists(".\\temp"))
            {
                Directory.CreateDirectory(".\\temp");
            }

            previewVideo = video;
            PreviewImage?.Clear();
            IsLoadingThumb = true;
            await PreviewTask(video);
            IsLoadingThumb = false;
            ShowThumbWindow();
        }

        public virtual double ProgressValue { get; set; }
        private async Task PreviewTask(VideoInfo file)
        {
            if (!IsVideo(file.Path))
            {
                ShowImageThumb(file);
                return;
            }

            ProgressValue = 5;
            var guid = Guid.NewGuid().ToString();
            TimeSpan duration = await FFmpegHelper.GetVideoDuration(file.Path);
            var gap = (duration.TotalSeconds - 0.5) / ThumbNum;
            TimeSpan timeSpan = TimeSpan.FromSeconds(gap);
            Task[] tasks = new Task[ThumbNum];
            for (int i = 0; i < ThumbNum; i++)
            {
                Task task = GenerateVideoPreview(file.Path, $".\\temp\\{guid}_{i + 1}.png", timeSpan.ToString(@"hh\:mm\:ss"));
                tasks[i] = task;
                timeSpan = timeSpan.Add(TimeSpan.FromSeconds(gap));
            }

            await Task.WhenAll(tasks);
            timeSpan = TimeSpan.FromSeconds(gap);
            for (int i = 0; i < ThumbNum; i++)
            {
                AddPreViewImage($"{guid}_{i + 1}", timeSpan);
                timeSpan = timeSpan.Add(TimeSpan.FromSeconds(gap));
                await Task.Delay(10);
            }
        }

        private void ShowImageThumb(VideoInfo file)
        {
            string imagePath = file.Path;
            var uri = new Uri(imagePath, UriKind.Absolute);

            // 创建一个新的 BitmapImage
            BitmapImage bitmap = new BitmapImage();
            // 开始初始化
            bitmap.BeginInit();
            // 设置图片的 UriSource
            bitmap.UriSource = uri;
            // 设置 CacheOption 为 OnLoad，这样图片加载后文件就会被释放
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            // 结束初始化
            bitmap.EndInit();
            // 确保图片在加载后立即释放文件
            bitmap.Freeze();

            // 将加载的图片设置为 PreviewImage
            PreviewImage?.Add(new PreviewInfo()
            {
                Image = bitmap,
            });
        }

        bool IsVideo(string path)
        {
            return extsVideo.Contains(Path.GetExtension(path).ToLower());
        }

        private void AddPreViewImage(string guid, TimeSpan time)
        {
            string imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $".\\temp\\{guid}.png");
            var uri = new Uri(imagePath, UriKind.Absolute);

            // 创建一个新的 BitmapImage
            BitmapImage bitmap = new BitmapImage();
            // 开始初始化
            bitmap.BeginInit();
            // 设置图片的 UriSource
            bitmap.UriSource = uri;
            // 设置 CacheOption 为 OnLoad，这样图片加载后文件就会被释放
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            // 结束初始化
            bitmap.EndInit();
            // 确保图片在加载后立即释放文件
            bitmap.Freeze();

            // 将加载的图片设置为 PreviewImage
            PreviewImage?.Add(new PreviewInfo()
            {
                Image = bitmap,
                Time = time
            });
        }

        public async Task GenerateVideoPreview(string videoPath, string imagePath, string timeStamp)
        {
            await FFmpegHelper.GenerateVideoPreview(videoPath, imagePath, timeStamp);
            ProgressValue += 1d / ThumbNum * 100d;
        }

        public virtual BitmapImage? DynamicImage { get; set; }

        public static void ShowDynamicImage(BitmapImage? img)
        {
            App.MainViewModel.DynamicImage = img;
        }
    }
}
